package grabana

import (
	
	
	
	
	

	
)

// ErrDatasourceNotFound is returned when the given datasource can not be found.
var ErrDatasourceNotFound = errors.New("datasource not found")

const defaultDatasourceKey = "$grabana_default_datasource_key$"

// UpsertDatasource creates or replaces a datasource.
func ( *Client) ( context.Context,  datasource.Datasource) error {
	,  := json.Marshal()
	if  != nil {
		return 
	}

	,  := .getDatasourceIDByName(, .Name())
	if  != nil && !errors.Is(, ErrDatasourceNotFound) {
		return 
	}

	 := http.MethodPost
	 := "/api/datasources"
	if  != 0 {
		 = http.MethodPut
		 = fmt.Sprintf("/api/datasources/%d", )
	}

	,  := .sendJSON(, , , )
	if  != nil {
		return 
	}

	defer func() { _ = .Body.Close() }()

	if .StatusCode != http.StatusOK {
		return .httpError()
	}

	return nil
}

// DeleteDatasource deletes a datasource given its name.
func ( *Client) ( context.Context,  string) error {
	,  := .getDatasourceIDByName(, )
	if  != nil {
		return 
	}

	,  := .delete(, fmt.Sprintf("/api/datasources/%d", ))
	if  != nil {
		return 
	}

	defer func() { _ = .Body.Close() }()

	if .StatusCode == http.StatusNotFound {
		return ErrDatasourceNotFound
	}
	if .StatusCode != http.StatusOK {
		return .httpError()
	}

	return nil
}

// GetDatasourceUIDByName finds a datasource UID given its name.
func ( *Client) ( context.Context,  string) (string, error) {
	,  := .get(, "/api/datasources/name/"+)
	if  != nil {
		return "", 
	}

	defer func() { _ = .Body.Close() }()

	if .StatusCode == http.StatusNotFound {
		return "", ErrDatasourceNotFound
	}

	if .StatusCode != http.StatusOK {
		return "", .httpError()
	}

	 := struct {
		 string `json:"uid"`
	}{}
	if  := decodeJSON(.Body, &);  != nil {
		return "", 
	}

	return ., nil
}

// datasourcesUIDMap builds a map of datasources UIDs indexed by their name.
func ( *Client) ( context.Context) (map[string]string, error) {
	,  := .get(, "/api/datasources")
	if  != nil {
		return nil, 
	}

	defer func() { _ = .Body.Close() }()

	if .StatusCode != http.StatusOK {
		return nil, .httpError()
	}

	var  []struct {
		       string `json:"uid"`
		      string `json:"name"`
		 bool   `json:"isDefault"`
	}
	if  := decodeJSON(.Body, &);  != nil {
		return nil, 
	}

	 := make(map[string]string, len())
	for ,  := range  {
		[.] = .

		if . {
			[defaultDatasourceKey] = .
		}
	}

	return , nil
}

// getDatasourceIDByName finds a datasource, given its name.
func ( *Client) ( context.Context,  string) (int, error) {
	,  := .get(, "/api/datasources/id/"+)
	if  != nil {
		return 0, 
	}

	defer func() { _ = .Body.Close() }()

	if .StatusCode == http.StatusNotFound {
		return 0, ErrDatasourceNotFound
	}

	if .StatusCode != http.StatusOK {
		return 0, .httpError()
	}

	 := struct {
		 int `json:"id"`
	}{}
	if  := decodeJSON(.Body, &);  != nil {
		return 0, 
	}

	return ., nil
}